import React, {Component} from 'react';
import { Form, Row, Col, Input, Button, Select, Cascader, DatePicker, TimePicker, Radio, Switch, AutoComplete } from 'antd';
import PropTypes from 'prop-types';
import ScTransfer from '../../dataEntry/scTransfer';
import options from '../../dataEntry/areaPickerOption';
import locale from 'antd/lib/date-picker/locale/zh_CN';
import '../../../assets/stylus/com/display/form.styl';
import moment from 'moment';
import {initModals} from "../../../state/action/comAction";
import RefreshGrid from '../../../utils/refreshGrid';
import fetchHandler from '../../../fetch/fetchHandler';
const FormItem = Form.Item;
const Option = Select.Option;
const AutoOption = AutoComplete.Option;
const TextArea = Input.TextArea;
const RangePicker = DatePicker.RangePicker;
const RadioGroup = Radio.Group;
/*
*  表单核心组件
*  @ option layout {String} 表单布局形式
*  @ option children {JSX} 表单插槽中定义的内容
* */

class FormCore extends Component {

  static contextTypes = {
    store: PropTypes.object.isRequired
  }

  constructor (props) {
    super();
    this.props = props;
    // 设置表单map
    this.state = {
      loading: !1,
      visible: {}
    };

    this.formMap = {
      'input': this.formInputHive.bind(this),
      'select': this.formSelectHive.bind(this),
      'buttonGp': this.formButtonGpHive.bind(this),
      'areaPicker': this.formAreaPickerHive.bind(this),
      'date': this.formDatePickerHive.bind(this),
      'switch': this.formSwitchHive.bind(this),
      'radio': this.formRadioHive.bind(this),
      'transfer': this.formTransferHive.bind(this),
      'autoWatch': this.formAutoHive.bind(this)
    };

    // 设置规则map

    this.rulesMap = {
      'phone': this.checkPhone.bind(this),
      'length': this.checkLength.bind(this),
      'check': this.checkSwitch.bind(this)
    }
  }

  componentDidMount () {
    const store = this.context.store;
    store.subscribe(() => {
      store.getState().modalInfo.visible === !1 && this.handleReset();
    });
  }

  generateAreaOptions (isPickArea) {
    if (this.options) {
      return this.options;
    } else {
      this.options = options(isPickArea);
      return this.options;
    }
  }

  // shouldComponentUpdate (nextProps, nextState) {
  //   // 重复渲染判断，将nextState转为新对象用来做对象判断，也可以使用immutable库。
  //   console.log(this.props);
  //   console.log(nextProps);
  //   return !Object.is(nextState, this.state) || !Object.is(this.props, nextProps);
  // }

  // 返回Input元素

  formInputHive (item) {
    return (
      item.inputType === 'textarea' ?
          <TextArea placeholder={item.placeholder}></TextArea> :
      <Input type={item.inputType} style={{width: '100%'}} disabled={item.disabled} placeholder={item.placeholder}/>
    )
  }

  // 返回自动联想元素
  formAutoHive (item) {
    this[item.param.name + 'origin'] || (this[item.param.name + 'origin'] = [], fetchHandler(item.sourceApi).then((res) => {
      const sourceData = {};
      if (res && res.code === 'success') {
        sourceData[item.param.name] = res.data;
        this[item.param.name + 'origin'] = res.data;
      } else {
        sourceData[item.param.name] = [];
      }
      this.setState(sourceData);
    }));
      return (
        <AutoComplete
        placeholder={item.placeholder}
        disabled={item.disabled}
        dataSource={this.state[item.param.name] ? this.state[item.param.name].map(s =>
          <AutoOption
            value={s[item.choseParam]}
            key = {s[item.choseParam]}
          >{s[item.showParam]}</AutoOption>
        ) : []}
        onSearch={(value) => this.handleSearch(value, this[item.param.name + 'origin'], item.showParam, item.param.name)}
        >
          <Input />
        </AutoComplete>
      );
  }

  handleSearch (v, source, showParam, name) {
    let filterSource = [];
    filterSource = source.filter((s) => {
      if (s[showParam].indexOf(v) !== -1) {
        return true;
      }
      return false;
    });
    const sourceData = {};
    sourceData[name] = filterSource;
    this.setState(sourceData);
  }

  // 返回Select元素

  formSelectHive (item) {
    return (
      <Select mode={item.selectType} style={{minWidth: '200px'}} placeholder={item.placeholder} onChange={(e) => this.visibleChange(e, item)}>
        {
          item.options.map((op) => (
            <Option key={op.text} value={op.value}>{op.text}</Option>
          ))
        }
      </Select>
    )
  }

  // 返回radio元素

  formRadioHive (item) {
    return (
      <RadioGroup onChange={(e) => this.visibleChange(e, item)}>
          {
            item.options.map((op) => (
              <Radio key={op.text} value={op.value}>{op.text}</Radio>
            ))
          }
      </RadioGroup>
    );
  }

  // 返回按钮交互元素

  formButtonGpHive (item) {
    const buttons = [];
    item.buttonArr.map((btn, index) => {
      btn.btnType === 'submit' &&
      buttons.push(
        <Button type={'primary'} loading={this.state.loading} className={'sc-form-btn'} key={'submit'} htmlType={'submit'}>{btn.text}</Button>
      );
      btn.btnType === 'formSubmit' &&
      buttons.push(
        <Button type={'primary'} loading={this.state.loading} className={'sc-form-btn'} key={'form_submit'} onClick={this.handleSubmit.bind(this)}>{btn.text}</Button>
      );
      btn.btnType === 'reset' &&
      buttons.push(
        <Button type={'default'} className={'sc-form-btn'} key={'reset'} onClick={this.handleReset.bind(this)}>{btn.text}</Button>
      );
      btn.btnType === 'button' &&
      buttons.push(
        <Button onClick={() => btn.handler(this)} type={'primary'} className={'sc-form-btn'} key={'button' + index}>{btn.text}</Button>
      );
    });
    return buttons;
  }

  // 构建地区联动选择

  formAreaPickerHive (item) {
    const areaDom = <Cascader changeOnSelect={item.pickOnSelect} style={{width: '100%'}} options={this.generateAreaOptions.bind(this)(item.isPickArea)} placeholder={item.placeholder} />;
    return areaDom;
  }

  // 构建日期选择

  formDatePickerHive (item) {
    const disabledDate = (current) => {
      if (item.range) {
        return current && current > moment().subtract(item.range[1], 'days') || (current && current < moment().subtract(item.range[0], 'days'));
      }
    };
    switch (item.dateType) {
      case 'pickDate':
        return <DatePicker disabledDate={disabledDate} locale={locale} placeholder={item.placeholder} />;
      case 'pickDateTime':
        return <DatePicker disabledDate={disabledDate} locale={locale} showTime format="YYYY-MM-DD HH:mm:ss" placeholder={item.placeholder} />;
      case 'rangeDate':
        return <RangePicker style={{width: '100%'}} disabledDate={disabledDate} locale={locale}/>
      case 'rangeDateTime':
        return <RangePicker style={{width: '100%'}} disabledDate={disabledDate} locale={locale} showTime format="YYYY-MM-DD HH:mm:ss"/>
      default:
        return <DatePicker disabledDate={disabledDate} locale={locale} placeholder={item.placeholder} />;
    }
  }

  // 构建开关
  formSwitchHive (item) {
   return <Switch/>;
  }

  // 构建穿梭框
  formTransferHive (item) {
    // 过滤inline布局
    if (this.props.formConfig.layout !== 'inline') {
      return <ScTransfer transferConfig={{
        type: item.transType,
        titles: item.titles,
        placeholder: item.placeholder,
        nofound: item.nofound,
        key: item.key,
        itemUnit: item.unit
      }
        // targetKeys: {}
      } />
    }
  }

  /*
  *  validate 定义
  * */
  // 验证字符串长度

  checkLength (rule, value, callback, item) {
    if (value && value.length > item.max_val || (value && value.length < item.min_val)) {
      callback(`内容长度请在${item.min_val}到${item.max_val}之间`);
    }
    callback();
  }

  // 验证手机号码

  checkPhone (rule, value, callback) {
    const phoneReg = /^[1][3,4,5,7,8][0-9]{9}$/;
    if (value && !phoneReg.test(value)) {
      callback('手机号码不正确');
    }
    callback();
  }

  // 验证开关

  checkSwitch (rule, value, callback) {
    if (!value) {
      callback('请勾选');
    }
    callback();
  }

  // 清空参数

  handleReset () {
    this.props.form.resetFields();
    this.context.store.getState().modalInfo.fetchParams && this.context.store.getState().modalInfo.fetchParams();
  }

  // 验证可见性
  visibleChange (e, item) {
    this.state.visible[item.param.name] = e.target ? e.target.value : e;
    this.setState({
      visible: this.state.visible
    });
  }

  // 提交查询

  handleSubmit (e) {
    e.preventDefault();
    this.props.form.validateFields((err, values) => {
      if (!err) {
        const fieldsValue = values;
        this.props.formConfig.childItems.forEach((item) => {
          if (item.type === 'date' && values[item.param.name]) {
            item.dateType === 'pickDate' && (fieldsValue[item.param.name] = values[item.param.name].format('YYYY-MM-DD'));
            item.dateType === 'pickDateTime' && (fieldsValue[item.param.name] = values[item.param.name].format('YYYY-MM-DD HH:mm:ss'));
            item.dateType === 'rangeDate' &&
            (fieldsValue[item.param.name] = [
              values[item.param.name][0].format('YYYY-MM-DD'),
              values[item.param.name][1].format('YYYY-MM-DD')
            ]);
            item.dateType === 'rangeDateTime' &&
            (fieldsValue[item.param.name] = [
              values[item.param.name][0].format('YYYY-MM-DD HH:mm:ss'),
              values[item.param.name][1].format('YYYY-MM-DD HH:mm:ss')
            ]);
          }
          if (item.radio && !item.radio.checked) {
            delete fieldsValue[item.param.name];
          }
          item.type === 'transfer' && (fieldsValue[item.param.name] = this.context.store.getState().modalInfo.param[item.key[1]].join(','));
        });
        let fieldsParam = {};
        this.loading();
        fieldsParam = this.props.formConfig.defaultParams ? Object.assign(fieldsValue, this.props.formConfig.defaultParams):
          fieldsValue;
        if (this.props.formConfig.formTarget === 'grid') {
          this.fetchGrid(fieldsParam);
          this.handleReset();
        } else {
          this.props.fetchApi(fieldsParam, this).then((res) => {
            // 执行请求返回成功， 执行清空
            if (res && res.code === 'success') {
              this.props.formConfig.formTarget === 'refresh' ? RefreshGrid(this.context.store).then(() => {
                // 请求成功并附带刷新grid调用
                this.setState({
                  loading: !1
                });
                this.context.store.dispatch(initModals(!1));
                this.handleReset();
              }) : (this.context.store.dispatch(
                // 请求成功无刷新grid调用
                initModals(!1),
                this.handleReset(),
                this.setState({
                loading: !1
              })));
            } else {
              // 请求失败调用
              this.setState({
                loading: !1
              });
              this.context.store.dispatch(initModals(!1));
            }
          });
        }
      }
    });
  }

  fetchGrid (fieldsParam) {
    const store = this.context.store;
    const params = this.props.formConfig.refresh ? store.getState().gridsInfo.param : Object.assign(store.getState().gridsInfo.param, fieldsParam);
    const context = store.getState().gridsInfo.context;
    const formRes = store.getState().gridsInfo.fetchDataHandler.bind(context)(!0, params);
    formRes.then((res) => {
      this.loaded();
    });
    return formRes;
  }

  loading () {
    this.setState({
      loading: !0
    });
  }

  loaded () {
    this.setState({
      loading: !1
    });
  }

  // radio选择Handler Fuc

  radioHandler (e, index, groupName) {
    this.props.formConfig.childItems.forEach((i) => {
      (i.radio && i.radio.radioGroup === groupName) && (i.radio.checked = !1);
    });
    this.props.formConfig.childItems[index].radio.checked = !0;
    const formConfig = Object.assign({}, this.props.formConfig);
    this.props.formConfig.context.setState({
      formConfig
    });
  }

  render () {
    const { getFieldDecorator } = this.props.form;
    const {layout, childItems} = this.props.formConfig;
    const formItemLayout = layout === 'horizontal' ? {
      labelCol: {
        xxl:{span: 3},
        xl: {span: 4},
        lg: {span: 5},
        md: {span: 6}
        },
      wrapperCol: { span: 8, offset: 0 },
    } : null;
    const buttonItemLayout = (type) => {
      return (layout === 'horizontal' && type === 'buttonGp') ? {
      wrapperCol: {
        xxl:{span: 14, offset: 3},
        xl: {span: 14, offset: 4},
        lg: {span: 14, offset: 5},
        md: {span: 14, offset: 6}
        },
    } : null}
    return <Form layout={layout} id={layout === 'inline' ? 'sc-form' : ''} onSubmit={this.handleSubmit.bind(this)}>
        {
          childItems.map((item, i) => (
            (!item.visibleRule || this.state.visible[item.visibleRule.name] === item.visibleRule.value) &&
            <FormItem className={layout === 'inline' ? 'sc-form-list' : 'sc-row'} key={item.type + '' +  i} label={item.labelName} {...formItemLayout} {...buttonItemLayout(item.type)} >
                <Row gutter={4}>
                  <Col span={item.radio ? 20 : item.button ? 14 : 24}>
                    {item.param ? getFieldDecorator(item.param.name,
                      {
                        rules: [
                          {
                            type: item.param.type,
                            required: item.required,
                            message: '请输入内容'
                          },
                          {
                            type: item.param.type,
                            validator: item.validator && ((rule, value, callback) => {
                              this.rulesMap[item.validator.vtype](rule, value, callback, item.validator)
                            })
                          }
                        ],
                        valuePropName: item.type === 'switch' ? 'checked': 'value',
                        initialValue: item.defaultValue
                      }
                    )(this.formMap[item.type](item)) : (this.formMap[item.type](item))}
                  </Col>
                  {
                    item.radio &&
                    <Col span={3} offset={1}>
                      <Radio className={item.radio.radioGroup}
                             onClick={(e) => this.radioHandler(e, i, item.radio.radioGroup)}
                             checked={item.radio.checked}/>
                    </Col>
                  }
                  {
                    item.button &&
                    <Col span={7} offset={1}>
                    <Button type={item.button.style}
                    onClick={(e) => item.button.handler(e, this)}
                    >{item.button.name}</Button>
                    </Col>
                  }
                </Row>
            </FormItem>
          ))
        }
    </Form>
  }
}

const WrapFormCore = Form.create()(FormCore);

export default WrapFormCore;

FormCore.propTypes = {
  formConfig: PropTypes.object,
  fetchApi: PropTypes.func
}

